//TerrainFX.h
//Created 06/02/14
//Created By Daniel Bowler
//
//Effect used to render the terrain in our game. 

#pragma once

#include "AbstractFX.h"

class TerrainFX : public AbstractFX
{
	//Ensure that the ShaderManager can access private functions - the constructor/
	//destructor. Thus, the ShaderManager will be the only class allowed to 
	//create/destroy Effects.
	friend ShaderManager;
public:
	//Per vertex structure.
	struct PerVertex
	{
		PerVertex()
		{
			//Init TexLayer (not used in Height based)
			TexLayer = XMFLOAT2(0.0f, 0.0f);
		}

		XMFLOAT3 PosL;
		XMFLOAT3 NormalL;
		XMFLOAT3 TangentL;
		XMFLOAT2 Tex;
		XMFLOAT2 TexLayer;   //Used to sample layer map. 
	};

	//Sets cbuffer data
	void SetCBufferPerObject(CXMMATRIX& world, 
		CXMMATRIX& worldInvTrans, CXMMATRIX& worldViewProj,
		Material& mat, 
		CXMMATRIX& worldView);

	//Set tex transforms
	void SetTexTransforms(CXMMATRIX& texTrans, CXMMATRIX& texDetailTrans);

	//Set lighting data.
	void SetLightingData(XMFLOAT3& eye, DirectionalLight* dLights, unsigned dLightCount, 
		ID3D11ShaderResourceView* lightListIndexBuffer, 
		ID3D11ShaderResourceView* lightListStartEndBuffer);

	//Set the texture map
	void SetTextureMap(ID3D11ShaderResourceView* textureMap, 
		ID3D11ShaderResourceView* detailMap,
		ID3D11ShaderResourceView* normalMap, 
		ID3D11ShaderResourceView* textureMap1,
		ID3D11ShaderResourceView* normalMap1,
		ID3D11ShaderResourceView* textureMap2,
		ID3D11ShaderResourceView* normalMap2,
		ID3D11ShaderResourceView* pomHM = 0,
		ID3D11ShaderResourceView* pomHM1 = 0,
		ID3D11ShaderResourceView* pomHM2 = 0, 
		ID3D11ShaderResourceView* specMap = 0,
		ID3D11ShaderResourceView* specMap1 = 0,
		ID3D11ShaderResourceView* specMap2 = 0);

	//Sets the layer data
	void SetLayerTexData(ID3D11ShaderResourceView* layerMap1, 
		ID3D11ShaderResourceView* layer1Tex, ID3D11ShaderResourceView* layer1Normal, 
		ID3D11ShaderResourceView* layer1Spec, ID3D11ShaderResourceView* layer1Height);

	//Set POM Data. 
	void SetPOMData(int minSamples, int maxSamples, 
		float heightScale0, float heightScale1, float heightScale2);

	//Set height based terrain data
	void SetHeightBasedPatchValues(float heightFac1, float heightFac2);

	//Sets hemispherical ambient colour data
	void SetHemisphericalData(XMFLOAT3 &hemiColDown, XMFLOAT3 &hemiColRange);

	//Set SSAO Map and transform data
	void SetSSAOData(ID3D11ShaderResourceView* ssaoTex, CXMMATRIX &transform);

	//Sets shadow map
	void SetShadowMap(ID3D11ShaderResourceView* shadowMap);
	void SetShadowMapMatricies(CXMMATRIX &view, CXMMATRIX &proj, CXMMATRIX &toTex);

	//Sets the clip plane
	void SetClipPlane(XMFLOAT4& clipPlane);

private:
	//Changes this so the ShaderManager will handle this automatically. 
	//
	//Set render target dimension data
	void SetRTDimensions(unsigned width, unsigned height);
	//Set Light List Buffer (Global lights buffer - Shader Manager can call this)
	void SetLightListBuffer(ID3D11ShaderResourceView* lightListBuffer);

private:
	TerrainFX(ID3D11Device* device);
	~TerrainFX();
	//Disable copy constrcutor and assignment operator
	TerrainFX(TerrainFX& copy);
	TerrainFX& operator=(TerrainFX& other);

	//Override the init methods.
	void InitInputLayout(ID3D11Device* device);
	void InitShaderVariablePointers();

private:
	//Variables.
	//
	//Cbuffer Data:
	ID3DX11EffectMatrixVariable* worldVar;
	ID3DX11EffectMatrixVariable* worldInvTransVar;
	ID3DX11EffectMatrixVariable* worldViewProjVar;

	//Tex transforms:
	//
	//This applies to the diffuse map and normal map (When implemented)
	ID3DX11EffectMatrixVariable* texTransformVar;
	//This applies to the detail map - and should be a one-to-one 
	//matrix transform (Scale by the number of pollys)
	ID3DX11EffectMatrixVariable* texTransformDetailVar;

	//Render dimensions
	ID3DX11EffectScalarVariable* rtWidthVar;
	ID3DX11EffectScalarVariable* rtHeightVar;

	//Lighting data
	ID3DX11EffectVectorVariable* eyePosVar;
	ID3DX11EffectVariable* materialVar;
	//Direc Lights
	ID3DX11EffectVariable* direcLightVar;
	ID3DX11EffectScalarVariable* direcLightCountVar;
	//Point/Spot lights - Tile Forward System
	ID3DX11EffectShaderResourceVariable* llbVar;
	ID3DX11EffectShaderResourceVariable* llibVar;
	ID3DX11EffectShaderResourceVariable* llsebVar;

	//Textures
	//
	//0
	ID3DX11EffectShaderResourceVariable* texMapVar;
	ID3DX11EffectShaderResourceVariable* texDetailMapVar;
	ID3DX11EffectShaderResourceVariable* texNormalMapVar;
	//1
	ID3DX11EffectShaderResourceVariable* texMap1Var;
	ID3DX11EffectShaderResourceVariable* texNormalMap1Var;
	//2
	ID3DX11EffectShaderResourceVariable* texMap2Var;
	ID3DX11EffectShaderResourceVariable* texNormalMap2Var;

	//POM Height maps - For us if the heights are in a seperate HM. 
	ID3DX11EffectShaderResourceVariable* hmVar;
	ID3DX11EffectShaderResourceVariable* hm1Var;
	ID3DX11EffectShaderResourceVariable* hm2Var;

	//Spec maps
	ID3DX11EffectShaderResourceVariable* specMapVar;
	ID3DX11EffectShaderResourceVariable* specMap1Var;
	ID3DX11EffectShaderResourceVariable* specMap2Var;

	//POM data
	ID3DX11EffectScalarVariable* pomMinSamplesVar;
	ID3DX11EffectScalarVariable* pomMaxSamplesVar;

	//POM Height Scale
	ID3DX11EffectScalarVariable* pomHeightScaleVar;
	ID3DX11EffectScalarVariable* pomHeightScale1Var;
	ID3DX11EffectScalarVariable* pomHeightScale2Var;

	//Height factors for height based rendering
	ID3DX11EffectScalarVariable* heightFac1Var;
	ID3DX11EffectScalarVariable* heightFac2Var;

	//Hemispheric Ambient lighting colours
	ID3DX11EffectVectorVariable* hemiColDownVar;
	ID3DX11EffectVectorVariable* hemiColRangeVar;

	//SSAO
	ID3DX11EffectMatrixVariable* worldViewVar;
	ID3DX11EffectShaderResourceVariable* ssaoMapVar;
	ID3DX11EffectMatrixVariable* ssaoWorldViewProjTexVar;

	//Shadow Map
	ID3DX11EffectShaderResourceVariable* shadowMapVar;
	ID3DX11EffectMatrixVariable* shadowMapViewVar;
	ID3DX11EffectMatrixVariable* shadowMapProjVar;
	ID3DX11EffectMatrixVariable* shadowMapToTexVar;

	//Cip Plane
	ID3DX11EffectVectorVariable* clipPlaneVar;

	//Layer map textures
	ID3DX11EffectShaderResourceVariable* layerMap1Var;

	//Layer textures. 
	ID3DX11EffectShaderResourceVariable* layer1TexVar;
	ID3DX11EffectShaderResourceVariable* layer1NormalVar;
	ID3DX11EffectShaderResourceVariable* layer1SpecVar;
	ID3DX11EffectShaderResourceVariable* layer1HeightVar;
};